#ifndef PROGRESS_LIST_VIEW_HEADER
#define PROGRESS_LIST_VIEW_HEADER

#include "atlctrlsext.h"

struct UserItemData {
    int isubitem;
    int progress;
    void *userdata;

    UserItemData() : isubitem(-1), progress(0), userdata(NULL)
    {}
};

template<typename T>
class CPBarListViewDraw: public CCustomListViewDraw<T> 
{
   
protected:

    void DrawRoundRect(CDCHandle dcPaint, CRect& rcRect, COLORREF rgbOuter, COLORREF rgbInner)
    {
        CRect rcRoundRect( rcRect );

        CPen penBorder;
        penBorder.CreatePen( PS_SOLID, 1, rgbOuter );
        CBrush bshInterior;

        bshInterior.CreateSolidBrush(GetSysColor(COLOR_WINDOW));

        dcPaint.SelectPen( penBorder );
        dcPaint.SelectBrush( bshInterior );

        dcPaint.RoundRect( rcRoundRect, CPoint( 5, 5 ) );
        rcRoundRect.DeflateRect( 1, 1 );

        CPen penInnerBorder;
        penInnerBorder.CreatePen( PS_SOLID, 1, rgbInner );
        dcPaint.SelectPen( penInnerBorder );

        dcPaint.RoundRect( rcRoundRect, CPoint( 2, 2 ) );
    }

   
    void DrawGradient(CDCHandle dcPaint, CRect& rcRect, COLORREF rgbTop, COLORREF rgbBottom)
    {
        GRADIENT_RECT grdRect = { 0, 1 };
        TRIVERTEX triVertext[ 2 ] = {
            rcRect.left,
            rcRect.top,
            GetRValue( rgbTop ) << 8,
            GetGValue( rgbTop ) << 8,
            GetBValue( rgbTop ) << 8,
            0x0000,			
            rcRect.right,
            rcRect.bottom,
            GetRValue( rgbBottom ) << 8,
            GetGValue( rgbBottom ) << 8,
            GetBValue( rgbBottom ) << 8,
            0x0000
        };

        dcPaint.GradientFill( triVertext, 2, &grdRect, 1, GRADIENT_FILL_RECT_V );
    }


    VOID DrawProgressBar(HDC hdc, LPRECT rcBar, BOOL bSmooth, INT iProgress) // by Napalm
    {
        CDCHandle dc(hdc);
        static COLORREF clr[2] = { RGB(170,240,170),  RGB(45, 210, 50) };

        CRect rcProgress(*rcBar);

        //rcProgress.DeflateRect( 3, 2 );
        DrawRoundRect(dc, rcProgress, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_BTNFACE));

        rcProgress.DeflateRect(3, 3);
        rcProgress.right = rcProgress.left + (int)( (double)rcProgress.Width() * ((max(min(iProgress, 100 ), 0)) / 100.0) );
        DrawGradient(dc, rcProgress, clr[0], clr[1]);

        TCHAR pct[32] = { 0 };

        ::_sntprintf(pct, 31, _T("%d%%"), iProgress);
        dc.DrawTextA(pct, lstrlen(pct), rcBar, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
        /*
        CBrush br;
        br.CreateSolidBrush(RGB(0xc0, 0xc0, 0xc0));

        HRGN hRgn = CreateRoundRectRgn(rcBar->left, rcBar->top, rcBar->right + 1, rcBar->bottom + 1, 4, 4);
        SelectClipRgn(hdc, hRgn);
        FillRgn(hdc, hRgn, br);
        SelectClipRgn(hdc, NULL);
        DeleteObject(hRgn);
        */
    }

public:

    struct LISTVIEWPROGRESS {
        INT  iSubItem;
        INT  iProgress;
        BOOL bSmooth;
    };

    DWORD OnPrePaint(int idCtrl, LPNMLVCUSTOMDRAW lpNMCustomDraw)
    {
        return CDRF_NOTIFYITEMDRAW;
    }

    DWORD OnItemPrePaint(int idCtrl, LPNMLVCUSTOMDRAW lpNMCustomDraw)
    { 
        /*
        NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( lpNMCustomDraw );    
        if  (pLVCD->nmcd.uItemState & CDIS_SELECTED) {
            COLORREF crText = RGB(200,200,255);
            // Store the color back in the NMLVCUSTOMDRAW struct.
            pLVCD->clrTextBk = crText;
        }
        */
        return CDRF_NOTIFYSUBITEMDRAW;
    }

    DWORD OnSubItemPrePaint(int /*idCtrl*/, LPNMLVCUSTOMDRAW lpNMCustomDraw)
    {
        return CDRF_NOTIFYSUBITEMDRAW | CDRF_NOTIFYPOSTPAINT;
    }

    DWORD OnSubItemPostPaint(int /*idCtrl*/, LPNMLVCUSTOMDRAW lpNMCustomDraw)
    {
        // Is this part of the drawing state for each sub-item?
        //if(pCustomDraw->nmcd.dwDrawStage == (CDDS_ITEMPOSTPAINT | CDDS_SUBITEM)){
       // LISTVIEWPROGRESS *lvp = reinterpret_cast<LISTVIEWPROGRESS *>(lpNMCustomDraw->nmcd.lItemlParam);

        UserItemData *udata = (UserItemData*)lpNMCustomDraw->nmcd.lItemlParam;
        if (udata) {
            // Does the current sub-item match the progress-bar sub-item? 
            if (lpNMCustomDraw->iSubItem == udata->isubitem) {
                RECT rcBar;
                // Get the sub-item rectangle.
                //ListView_GetSubItemRect(lpNMHdr->hwndFrom, pCustomDraw->nmcd.dwItemSpec, 
                //    pCustomDraw->iSubItem, LVIR_BOUNDS, &rcBar);
                T *pT = static_cast<T*>(this);
                ListView_GetSubItemRect(pT->m_hWnd, lpNMCustomDraw->nmcd.dwItemSpec, 
                    lpNMCustomDraw->iSubItem, LVIR_BOUNDS, &rcBar);
                // Get a little extra room.
                //InflateRect(&rcBar, -2, -2);
                // Draw the progress bar to the sub-item location.
                //DrawProgressBar(lpNMCustomDraw->nmcd.hdc, &rcBar, lvp->bSmooth, lvp->iProgress);
                DrawProgressBar(lpNMCustomDraw->nmcd.hdc, &rcBar, true, udata->progress);
                // Skip the default drawing action since we've done this stages drawing.
                return CDRF_SKIPDEFAULT;
            }
            return CDRF_DODEFAULT | CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYSUBITEMDRAW;
        }
        else
            return CDRF_DODEFAULT;
        //// Else do the default drawing action and request we get post-subitem drawing notification.

    }

};

#endif